<?php

namespace app\install\controller;

use think\App;
use app\BaseController;
use think\facade\Config;
use think\facade\Db;
use think\facade\View;
use \PDO;

class Index extends BaseController
{

    use \app\common\traits\JumpTrait;

    protected $config;

    //错误信息
    protected $msg = '';

    //安装文件
    protected $lockFile;

    //数据库
    protected $databaseConfigFile;

    //sql 文件
    protected $sqlFile = '';

    //mysql版本
    protected $mysqlVersion = '5.6';

    //database模板
    protected $databaseTpl = '';

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->databaseConfigFile = config_path()."database.php";
        $this->sqlFile            = app_path()."huicms.sql";
        $this->lockFile           = public_path()."install.lock";
        $this->databaseTpl        = app_path()."view/tpl/database.tpl";
        $this->config             = [
            'siteName'    => config('ver.cms_app'),
            'siteVersion' => config('ver.cms_version'),
            'tablePrefix' => "cms_",
            'runtimePath' => runtime_path(),
            'lockFile'    => $this->lockFile,
            'envFile'     => public_path().'../.env'
        ];


        if (request()->action() != 'step4' && file_exists($this->lockFile)) {
            $this->error('当前版本已经安装了，如果需要重新安装请先删除install.lock', '/admin.php');
        }
        View::assign('config', $this->config);
    }

    public function index()
    {
        return redirect('/install/index/step1');
    }

    public function step1()
    {
        return view('step1');
    }

    public function step2()
    {
        $data['php_version']  = PHP_VERSION;
        $data['pdo']          = extension_loaded("PDO");
        $data['mysqli']       = extension_loaded("mysqli");
        $data['open_basedir'] = ini_get('open_basedir');;
        $data['database'] = is_really_writable($this->databaseConfigFile);
        $data['gd_info']  = function_exists('gd_info') || class_exists('Imagick', false);

        return view('step2', ['data' => $data]);

    }

    public function step3()
    {
        // 检测环境页面
        if (request()->action() === 'step3' && request()->isGet()) {
            return view('step3');
        }
        if (request()->action() === 'step3' && request()->isPost()) {
            //执行安装
            $db['host'] = request()->post('hostname') ? request()->post('hostname') : '127.0.0.1';
            $db['port'] = request()->post('port') ?: '3306';
            //判断是否在主机头后面加上了端口号
            $hostData = explode(":", $db['host']);
            if (isset($hostData) && $hostData && is_array($hostData) && count($hostData) > 1) {
                $db['host'] = $hostData[0];
                $db['port'] = $hostData[1];
            }
            //mysql的账户相关
            $db['username']      = request()->post('username') ?: 'root';
            $db['password']      = request()->post('password') ?: '123456';
            $db['database']      = request()->post('database') ?: 'huicms';
            $db['prefix']        = request()->post('prefix') ?: $this->config['tablePrefix'];
            $db['prefix']        = rtrim($db['prefix'], "_")."_";
            $admin['username']   = request()->post('adminUserName') ?: 'admin';
            $admin['password']   = request()->post('adminPassword') ?: '123456';
            $admin['repassword'] = request()->post('rePassword') ?: '123456';
            $admin['email']      = request()->post('email') ?: 'admin@admin.com';
            if (file_exists($this->lockFile)) {
                $this->error('当前版本已经安装了，如果需要重新安装请先删除install.lock');
            }
            //php 版本
            if (version_compare(PHP_VERSION, '7.3.0', '<')) {
                $this->error('当前版本(" . PHP_VERSION . ")过低，请使用PHP7.3.0以上版本');
            }
            if ( ! extension_loaded("PDO")) {
                $this->error('当前未开启PDO，无法进行安装');
            }
            //判断两次输入是否一致
            if ($admin['password'] != $admin['repassword']) {
                $this->error('两次输入密码不一致！');
            }
            if ( ! preg_match('/^[0-9a-z_$]{6,16}$/i', $admin['password'])) {
                $this->error('密码必须6-16位,且必须包含字母和数字,不能有中文和空格');

            }
            if ( ! preg_match("/^\w+$/", $admin['username'])) {
                $this->error('用户名只能输入字母、数字、下划线！');
            }
            if (strlen($admin['username']) < 3 || strlen($admin['username']) > 12) {
                $this->error('用户名请输入3~12位字符！');
            }
            if (strlen($admin['password']) < 5 || strlen($admin['password']) > 16) {
                $this->error('密码请输入5~16位字符！');
            }
            //检测能否读取安装文件
            $sql = @file_get_contents($this->sqlFile);
            if ( ! $sql) {
                $this->error("无法读取{$this->sqlFile}文件，请检查是否有读权限");
            }
            // 连接数据库
            try {
                $pdo = new PDO("mysql:host={$db['host']};port={$db['port']}", $db['username'], $db['password'], array(
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
                ));
            } catch (\Exception $e) {
                $this->error("数据库连接失败：".$e->getMessage());
            }

            $pdo->query("SET NAMES 'utf8mb4'");//

            //检测mysql版本是否符合要求（最低需要5.6版本）
            $res    = $pdo->query("select VERSION()");
            $result = $res->fetch();
            if ($result[0] < 5.6) {
                $this->error("本系统需要数据库版本最低为5.6，当前数据库版本为".$result[0]);
            }
            $pdo->query("CREATE DATABASE IF NOT EXISTS `{$db['database']}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
            $pdo->query("USE `{$db['database']}`");

            // 写入数据库
            $sql = file_get_contents($this->sqlFile);
            $sql = str_replace(["`cms_", 'CREATE TABLE'], ["`{$db['prefix']}", 'CREATE TABLE IF NOT EXISTS'], $sql);

            $EnvFile = root_path().".env";

            $configDb = [
                'hostname' => trim($db['host']),
                'database' => trim($db['database']),
                'username' => trim($db['username']),
                'password' => trim($db['password']),
                'hostport' => trim($db['port']),
                'prefix'   => trim($db['prefix'])
            ];
            @file_put_contents($EnvFile, $this->writeEnv($configDb));
            try {
                $pdo->query($sql);
                sleep(2);
                $password = passwordHash($admin['password']);
                $pdo->query("UPDATE {$db['prefix']}admin SET `email`='{$admin['email']}',`username` = '{$admin['username']}',`password` = '{$password}' WHERE `username` = 'admin'");
            } catch (\PDOException $e) {
                $this->error($e->getMessage());
            } catch (\Exception $e) {
                $this->error($e->getMessage());
            }

            $result = @touch($this->lockFile);
            if ( ! $result) {
                $this->error("安装失败、请确定install.lock是否有写入权限");
            }
            $adminUser['username'] = $admin['username'];
            $adminUser['password'] = $admin['password'];
            session('admin_install', $adminUser);
            $this->success('安装成功,安装后请重新启动程序');
        }
    }

    public function step4()
    {
        //完成安装
        if (request()->isPost()) {
            session('admin_install', '');
            $this->success('OK');
        }

        return view('step4');
    }

    /**
     * 写入 .env文件
     */
    private function writeEnv($data)
    {
        $hostname = $data['hostname'];
        $database = $data['database'];
        $username = $data['username'];
        $password = $data['password'];
        $hostport = $data['hostport'];
        $prefix   = $data['prefix'];
        $config   = <<<EOT
APP_DEBUG = true

[APP]
DEFAULT_TIMEZONE = Asia/Shanghai

[DATABASE]
TYPE = mysql
HOSTNAME = $hostname
DATABASE = $database
USERNAME = $username
PASSWORD = $password
PREFIX = $prefix
HOSTPORT = $hostport
CHARSET = utf8mb4
DEBUG = true

[LANG]
default_lang = zh-cn

EOT;

        return $config;

    }

    // 检测目录权限
    function dirTestWrite($path)
    {
        if ($fp = @fopen($path.'demo.txt', 'w')) {
            @fclose($fp);
            @unlink($path.'demo.txt');

            return true;
        }

        return false;
    }

}
